<?php
class Develop_Model_Code
{
    protected 	$_properties = array();
    protected 	$_methods = array();
    protected	$_module = null;
    protected	$_table = null;
    protected	$_tableName = null;


    function __construct($module,$table)
    {
        $this->_module = $module;
        $this->_table = $table;
        $tt = explode("_",$table);
        $table_name='';
        foreach($tt as $val)
        $table_name.= ucfirst($val);
        $this->_tableName = $table_name;
    }

    function _init()
    {
        unset($this->_properties);
        unset($this->_methods);
    }

    function getLanguage()
    {
        $str = '';
        $db = Zend_Db_Table:: getDefaultAdapter();
        $columns = $db->query("SHOW FULL COLUMNS FROM ".$this->_table)->fetchAll();

        foreach($columns as $col){
            if ($col['Comment'])
            $str .= "'".$col['Field']."' =>'".$col['Comment']."',\n";
            else
            $str .= "'".$col['Field']."' =>'".$col['Field']."',\n";
        }
        $str = "return array(\n".$str.");";
        //	'id:' => '流水號',
        return $str;
    }


    function getForm()
    {
        $this->_init();
        $db = Zend_Db_Table:: getDefaultAdapter();

        $columns = $db->describeTable($this->_table);

        $docblock  = new Zend_CodeGenerator_Php_Docblock(array(
                'shortDescription' => 'initialization routine ',
        //	  'longDescription' => 'Lazy loads '.ucfirst($this->_module).'_Model_'.$this->_tableName.' if no instance registered',
                'tags'             => array(

        new Zend_CodeGenerator_Php_Docblock_Tag_Return(array(
								'datatype'  => 'void',

        )),
        ),
        ));
        //print_r($columns);
        $body = "\$this->setMethod('post');\n";

        foreach($columns as $name=>$col) {
            $body .= "\$this->addElement('text', '".$name."', array(\n";
            $body .= "	'label'      => '$name',\n";
            $body .= "	'required'   => true,\n";
            $body .= "	'filters'    => array('StringTrim'),\n";
            $body .= "//	'validators' => array()\n";
            $body .= "	)\n";
            $body .= ");\n";

        }
        $this->_methods[] = array(
				'name'=> 'init',
				'body'       => $body,
				'docblock' => $docblock
        );

        $docblock = new Zend_CodeGenerator_Php_Docblock(array(
    'shortDescription' => $this->_tableName.' form',
    'tags'             => array(
        array(
            'name'        => 'version',
            'description' => '$Id: Code.php 143 2010-07-20 07:35:54Z yingkuang.chen@gmail.com $',
        ),
        array(
            'name'        => 'license',
            'description' => 'New BSD License',
        ),
        array(
            'name'        => 'uses',
            'description' => 'Zend_Form',

        ),
        array(
            'name'        => 'package',
            'description' => $this->_module,
        ),
        array(
            'name'        => 'subpackage',
            'description' => 'Form',
        ),

        ),
        ));
        $form  = new Zend_CodeGenerator_Php_Class();
        $form->setName(ucfirst($this->_module).'_Form_'.$this->_tableName)
        ->setExtendedClass('Sfs_Form')
        ->setDocblock($docblock)
        //->setProperties($this->_properties);
        ->setMethods($this->_methods);

        return $form->generate();
    }

    /**
     * DbTable code
     * @return string
     */
    function getDbTable()
    {
        $this->_init();
        $dbTable      = new Zend_CodeGenerator_Php_Class();
        $this->_properties[] = array(
				'name' => '_name',
				'visibility'  => 'protected',
				'defaultValue' => $this->_table,
        //				'docblock'=>$docblock2
        );


        $docblock = new Zend_CodeGenerator_Php_Docblock(array(
    'shortDescription' => $this->_tableName.' table data gateway',
    'tags'             => array(
        array(
            'name'        => 'version',
            'description' => '$Id: Code.php 143 2010-07-20 07:35:54Z yingkuang.chen@gmail.com $',
        ),
        array(
            'name'        => 'license',
            'description' => 'New BSD License',
        ),
        array(
            'name'        => 'uses',
            'description' => 'Zend_Db_Table_Abstract',

        ),
        array(
            'name'        => 'package',
            'description' => $this->_module,
        ),
        array(
            'name'        => 'subpackage',
            'description' => 'Model',
        ),

        ),
        ));


        $dbTable->setName(ucfirst($this->_module).'_'.'Model_DbTable_'.$this->_tableName)
        ->setExtendedClass('Zend_Db_Table_Abstract')
        ->setDocblock($docblock)
        ->setProperties($this->_properties);
        //->setMethods($this->_methods);

        return $dbTable->generate();
    }

    /**
     * Generator DataMapper
     * @return string
     */
    function getMapper()
    {
        $this->_init();
        $module = $this->_module;
        $table = $this->_table;
        $tabel_name = $this->_tableName;

        $mapper      = new Zend_CodeGenerator_Php_Class();

        $conn = Doctrine_Manager::connection();
        $this->_default();
        $columns = $conn->import->listTableColumns($table);

        $this->_properties[] = array(
				'name' => '_dbTable',
				'visibility'  => 'protected',
        //				'docblock'=>$docblock2
        );

        $docblock  = new Zend_CodeGenerator_Php_Docblock(array(
                'shortDescription' => 'Specify Zend_Db_Table instance to use for data operations',
                'tags'             => array(
        new Zend_CodeGenerator_Php_Docblock_Tag_Param(array(
                        'paramName' => '$dbTable',
                        'datatype'  => 'Zend_Db_Table_Abstract'
                        )),

                        new Zend_CodeGenerator_Php_Docblock_Tag_Return(array(
								'datatype'  => ucfirst($this->_module).'_Model_'.$this->_tableName.'Mapper',

                        )),
                        ),
                        ));
                        $this->_methods[] = array(
				'name'=> 'setDbTable',
				'parameters' => array(array('name' => 'dbTable')),
				'body'       => "if (is_string(\$dbTable)) {\n	\$dbTable = new \$dbTable();\n}\n".
        		"if (!\$dbTable instanceof Zend_Db_Table_Abstract) {\n".
            "	throw new Exception('Invalid table data gateway provided');\n".
        		"}\n".
        		"\$this->_dbTable = \$dbTable;\n".
        		"return \$this;",
				'docblock' => $docblock
                        );

                        $docblock  = new Zend_CodeGenerator_Php_Docblock(array(
                'shortDescription' => 'Get registered Zend_Db_Table instance',
					  'longDescription' => 'Lazy loads '.ucfirst($this->_module).'_Model_'.$this->_tableName.' if no instance registered',
                'tags'             => array(

                        new Zend_CodeGenerator_Php_Docblock_Tag_Return(array(
								'datatype'  => 'Zend_Db_Table_Abstract',

                        )),
                        ),
                        ));
                        $this->_methods[] = array(
				'name'=> 'getDbTable',
				'body'       => "if (null === \$this->_dbTable) {\n".
            	"\$this->setDbTable('".ucfirst($this->_module).'_Model_DbTable_'.$this->_tableName."');\n".
        		"}\n".
        		"return \$this->_dbTable;",
				'docblock' => $docblock
                        );

                        $docblock  = new Zend_CodeGenerator_Php_Docblock(array(
                'shortDescription' => 'Find a '.$this->_table.' entry by a key',
                'tags'             => array(
                        new Zend_CodeGenerator_Php_Docblock_Tag_Param(array(
                        'paramName' => 'id',
                        'datatype'  => 'int'
                        )),
                        new Zend_CodeGenerator_Php_Docblock_Tag_Param(array(
                        'paramName' => $this->_table,
                        'datatype'  => ucfirst($this->_module).'_Model_'.$this->_tableName
                        )),
                        new Zend_CodeGenerator_Php_Docblock_Tag_Return(array(
								'datatype'  => 'void',

                        )),
                        ),
                        ));
                        //print_r($columns);
                        $body= "\$data = array(\n";
                        foreach ($columns as $name=>$col) {
                            if (!$col['PRIMARY'])
                            $body .= "	'".$name."' => \$".$this->_table."->get".ucfirst($name)."(),\n";
                            else
                            $primary_function = "\$".$this->_table."->get".ucfirst($name)."()\n";
                        }
                        $body .=");\n";
                        $body .="if (null === (\$sn = ".$primary_function.")) {\n";
                        $body .="	unset(\$data['sn']);\n";
                        $body .="	\$this->getDbTable()->insert(\$data);\n";
                        $body .="} else {\n";
                        $body .="	\$this->getDbTable()->update(\$data, array('sn = ?' => \$sn));\n";
                        $body .="}";


                        $this->_methods[] = array(
				'name'=> 'save',
				'body'=> $body,
				'parameters' => array(array('name' => $this->_table,'datatype'=>ucfirst($this->_module).'_Model_'.$this->_tableName)),
				'docblock' => $docblock
                        );

                        $docblock  = new Zend_CodeGenerator_Php_Docblock(array(
                'shortDescription' => 'Save a '.$this->_table.' entry',
                'tags'             => array(
                        new Zend_CodeGenerator_Php_Docblock_Tag_Param(array(
                        'paramName' => $this->_table,
                        'datatype'  => ucfirst($this->_module).'_Model_'.$this->_tableName
                        )),

                        new Zend_CodeGenerator_Php_Docblock_Tag_Return(array(
								'datatype'  => 'void',

                        )),
                        ),
                        ));
                        //print_r($columns);
                        $body  ="\$result = \$this->getDbTable()->find(\$id);\n";
                        $body .="if (0 == count(\$result)) {\n";
                        $body .="	return;\n";
                        $body .="}\n";
                        $body .="\$row = \$result->current();\n";
                        $body .="\$".$this->_table;
                        foreach ($columns as $name=>$col) {
                            $body .= "->set".ucfirst($name)."(\$row->".$name.")\n	";
                        }
                        $body .=";\n";


                        $this->_methods[] = array(
				'name'=> 'find',
				'body'=> $body,
				'parameters' => array(array('name'=>'id'),array('name' => $this->_table,'datatype'=>ucfirst($this->_module).'_Model_'.$this->_tableName)),
				'docblock' => $docblock
                        );


                        $docblock  = new Zend_CodeGenerator_Php_Docblock(array(
                'shortDescription' => 'Fetch all '.$this->_table.' entries',
                'tags'             => array(
                        new Zend_CodeGenerator_Php_Docblock_Tag_Return(array(
								'datatype'  => 'array',

                        )),
                        ),
                        ));

                        $body  ="\$resultSet = \$this->getDbTable()->fetchAll();\n";
                        $body .="\$entries   = array();\n";
                        $body .="foreach (\$resultSet as \$row) {\n";
                        $body .="	\$entry = new ".ucfirst($this->_module).'_Model_'.$this->_tableName."();\n";
                        $body .="	\$entry";
                        foreach ($columns as $name=>$col) {
                            $body .= "->set".ucfirst($name)."(\$row->".$name.")\n	";
                        }
                        $body .=";\n";
                        $body .="	\$entries[] = \$entry;\n";
                        $body .="}\n";
                        $body .="return \$entries;";


                        $this->_methods[] = array(
				'name'=> 'fetchAll',
				'body'=> $body,
                        //'parameters' => array(array('name'=>'id'),array('name' => $this->_table,'datatype'=>ucfirst($this->_module).'_Model_'.$this->_tableName)),
				'docblock' => $docblock
                        );



                        //class infomation
                        $docblock = new Zend_CodeGenerator_Php_Docblock(array(
    'shortDescription' => $this->_tableName.' data mapper',
    'longDescription'  => 'Implements the Data Mapper design pattern',
    'tags'             => array(
                        array(
            'name'        => 'version',
            'description' => '$Id: Code.php 143 2010-07-20 07:35:54Z yingkuang.chen@gmail.com $',
                        ),
                        array(
            'name'        => 'license',
            'description' => 'New BSD License',
                        ),
                        array(
            'name'        => 'uses',
            'description' => ucfirst($this->_module).'_Model_DbTable_'.$this->_tableName,

                        ),
                        array(
            'name'        => 'package',
            'description' => $this->_module,
                        ),
                        array(
            'name'        => 'subpackage',
            'description' => 'Model',
                        ),

                        ),
                        ));

   //   ->setExtendedClass('Zend_Db_Table_Abstract')
                        $mapper->setName(ucfirst($module).'_'.'Model_'.$this->_tableName."Mapper")
                        ->setDocblock($docblock)
                        ->setProperties($this->_properties)
                        ->setMethods($this->_methods);

                        return $mapper->generate();


    }


    /**
     * Utilizes the Data Mapper pattern to persist data. Represents a single
     * @param $module module name
     * @param $table table name
     * @return string
     */
    function getModelTable()
    {
        $this->_init();
        $module = $this->_module;
        $table = $this->_table;
        $tabel_name = $this->_tableName;


        $conn = Doctrine_Manager::connection();
        $this->_default();
        $columns = $conn->import->listTableColumns($table);
//print_r($columns) ;exit;
        $this->_properties[] = array(
				'name' => "_mapper",
				'visibility'  => 'protected',
        //				'docblock'=>$docblock2
        );
        foreach ($columns as $name=>$col)
        {
            $docblock_set  = new Zend_CodeGenerator_Php_Docblock(array(
                'shortDescription' => 'Set the '.$name.' property',
                'tags'             => array(
            new Zend_CodeGenerator_Php_Docblock_Tag_Param(array(
                        'paramName' => $name,
                        'datatype'  => $col['ntype']
            )),
            new Zend_CodeGenerator_Php_Docblock_Tag_Return(array(
                        'datatype'  => $table_name
            )),
            ),
            ));

            $docblock_get  = new Zend_CodeGenerator_Php_Docblock(array(
                'shortDescription' => 'Retrieve the '.$name.' property',
                'tags'             => array(

            new Zend_CodeGenerator_Php_Docblock_Tag_Return(array(
								'datatype'  => $col['ntype'],

            )),
            ),
            ));

            $this->_methods[] = array(
				'name'=> 'set'.ucfirst($name),
				'parameters' => array(array('name' => $name)),
				'body'       => '$this->_'.$name. ' = $'.$name.';' . "\n" . 'return $this;',
				'docblock' => $docblock_set
            );
            $this->_methods[] = array(
				'name'=> 'get'.ucfirst($name),
				'body'       => 'return $this->_'.$name. ';',
				'docblock' => $docblock_get
            );

            $docblock_setoption  = new Zend_CodeGenerator_Php_Docblock(array(
                'shortDescription' => 'Set object state',
                'tags'             => array(

            new Zend_CodeGenerator_Php_Docblock_Tag_Return(array(
								'datatype'  => ucfirst($module).'_'.'Model_'.$this->_tableName,

            )),
            ),
            ));
            $this->_properties[] = array(
				'name' => "_".$name,
				'visibility'  => 'protected',
            //				'docblock'=>$docblock2
            );

        }


        $this->_methods[] = array(
				'name'=> 'setOptions',
				'parameters' => array(array('name' => 'options')),
				'body'       => "\$methods = get_class_methods(\$this);\n".
        		"foreach (\$options as \$key => \$value) {\n".
            "	\$method = 'set' . ucfirst(\$key);\n".
            "	if (in_array(\$method, \$methods)) {\n".
            "		\$this->\$method(\$value);\n".
            	"	}\n".
        		"}\n".
        		"return \$this;\n",
				'docblock' => $docblock_setoption
        );



        $foo      = new Zend_CodeGenerator_Php_Class();

        $docblock = new Zend_CodeGenerator_Php_Docblock(array(
    'shortDescription' => $this->_tableName.' Model',
    'longDescription'  => 'Utilizes the Data Mapper pattern to persist data. Represents a single'."\n".$table." entry",
    'tags'             => array(
        array(
            'name'        => 'version',
            'description' => '$Id: Code.php 143 2010-07-20 07:35:54Z yingkuang.chen@gmail.com $',
        ),
        array(
            'name'        => 'license',
            'description' => 'New BSD License',
        ),
        array(
            'name'        => 'uses',
            'description' => ucfirst($this->_module).'_Model_'.$this->_tableName.'Mapper',
        ),
        array(
            'name'        => 'package',
            'description' => $this->_module,
        ),
        array(
            'name'        => 'subpackage',
            'description' => 'Model',
        ),

        ),
        ));




        $foo->setName(ucfirst($module).'_'.'Model_'.$this->_tableName)
        //	->setExtendedClass('Zend_Db_Table_Abstract')
        ->setDocblock($docblock)
        ->setProperties($this->_properties)
        ->setMethods($this->_methods);

        return $foo->generate();
    }

    /**
     *  default function
     * @return void
     */

    protected function _default()
    {
        $docblock  = new Zend_CodeGenerator_Php_Docblock(array(
                'shortDescription' => 'Constructor',
                'tags'             => array(
        new Zend_CodeGenerator_Php_Docblock_Tag_Param(array(
                        'paramName' => '$options',
                        'datatype'  => 'array|null'
                        )),
                        new Zend_CodeGenerator_Php_Docblock_Tag_Return(array(
                        'datatype'  => 'void'
                        )),
                        ),
                        ));



                        $this->_methods[] = array(
				'name'=> '__construct',
				'parameters' => array(array('name' => 'options','defaultValue'=>null )),
				'body'       => 'if (is_array($options)) {'."\n".'$this->setOptions($options);'."\n".'}',

				'docblock' => $docblock
                        );
                        $docblock  = new Zend_CodeGenerator_Php_Docblock(array(
                'shortDescription' => 'Overloading: allow property access',
                'tags'             => array(
                        new Zend_CodeGenerator_Php_Docblock_Tag_Param(array(
                        'paramName' => '$name',
                        'datatype'  => 'string'
                        ),
                        array(
                        'paramName' => '$value',
                        'datatype'  => 'mixed'
                        )
                        ),
                        new Zend_CodeGenerator_Php_Docblock_Tag_Return(array(
                        'datatype'  => 'void'
                        )),
                        ),
                        ));

                        $this->_methods[] = array(
				'name'=> '__set',
				'parameters' => array(array('name' => 'name'),array('name' => 'value')),
				'body'       => " \$method = 'set' . \$name;\n".
        		"if ('mapper' == \$name || !method_exists(\$this, \$method)) { \n".
            "		throw Exception('Invalid property specified');\n".
        		" }\n".
        		"\$this->\$method(\$value);",
				'docblock' => $docblock
                        );


                        $this->_methods[] = array(
				'name'=> '__get',
				'parameters' => array(array('name' => 'name')),
				'body'       => " \$method = 'get' . \$name;\n".
        		"if ('mapper' == \$name || !method_exists(\$this, \$method)) { \n".
            "		throw Exception('Invalid property specified');\n".
        		" }\n".
        		"\$this->\$method();",
				'docblock' => $docblock
                        );

                        $docblock  = new Zend_CodeGenerator_Php_Docblock(array(
                'shortDescription' => 'Set data mapper',
                'tags'             => array(
                        new Zend_CodeGenerator_Php_Docblock_Tag_Param(array(
                        'paramName' => '$mapper',
                        'datatype'  => 'mixed'
                        )
                        ),
                        new Zend_CodeGenerator_Php_Docblock_Tag_Return(array(
                        'datatype'  => ucfirst($this->_module).'_Model_'.$this->_tableName.'Mapper'
                        )),
                        ),
                        ));


                        $this->_methods[] = array(
				'name'=> 'setMapper',
				'parameters' => array(array('name' => 'mapper')),
				'body'       => "\$this->_mapper = \$mapper;\n	return \$this;",
				'docblock' => $docblock
                        );

                        $docblock  = new Zend_CodeGenerator_Php_Docblock(array(
                'shortDescription' => 'Get data mapper',
					 'longDescription' => 'Lazy loads '.ucfirst($this->_module).'_'.$this->_tableName.'Mapper instance if no mapper registered.',
                'tags'             => array(
                        new Zend_CodeGenerator_Php_Docblock_Tag_Return(array(
                        'datatype'  => ucfirst($this->_module).'_'.$this->_tableName.'Mapper'
                        )),
                        ),
                        ));


                        $this->_methods[] = array(
				'name'=> 'getMapper',
				'body'       => " if (null === \$this->_mapper) {\n".
            "	\$this->setMapper(new ".ucfirst($this->_module).'_Model_'.$this->_tableName."Mapper());\n".
        		"}\n".
        		"return \$this->_mapper;",
				'docblock' => $docblock
                        );

                        $docblock  = new Zend_CodeGenerator_Php_Docblock(array(
                'shortDescription' => 'Save the current entry',
                'tags'             => array(
                        new Zend_CodeGenerator_Php_Docblock_Tag_Return(array(
                        'datatype'  => 'void'
                        )),
                        ),
                        ));


                        $this->_methods[] = array(
				'name'=> 'save',
				'body'       => "\$this->getMapper()->save(\$this);",
				'docblock' => $docblock
                        );

                        $docblock  = new Zend_CodeGenerator_Php_Docblock(array(
                'shortDescription' => 'Find an entry',
					 'longDescription' => 'Resets entry state if matching id found.',
                'tags'             => array(
                        new Zend_CodeGenerator_Php_Docblock_Tag_Param(array(
                        'paramName' => '$id',
                        'datatype'  => 'int'
                        )
                        ),
                        new Zend_CodeGenerator_Php_Docblock_Tag_Return(array(
                        'datatype'  => ucfirst($this->_module).'_Module_'.$this->_tableName
                        )),
                        ),
                        ));


                        $this->_methods[] = array(
				'name'=> 'find',
            'parameters' => array(array('name' => 'id')),
				'body'       => "\$this->getMapper()->find(\$id, \$this);\nreturn \$this;",
				'docblock' => $docblock
                        );

                        $docblock  = new Zend_CodeGenerator_Php_Docblock(array(
                'shortDescription' => 'Fetch all entries',
                'tags'             => array(
                        new Zend_CodeGenerator_Php_Docblock_Tag_Return(array(
                        'datatype'  => 'array'
                        )),
                        ),
                        ));


                        $this->_methods[] = array(
				'name'=> 'fetchAll',
				'body'       => "return \$this->getMapper()->fetchAll();",
				'docblock' => $docblock
                        );

    }
}
